﻿package com.teaphy.coroutinecrawler.compose_suspend

import kotlinx.coroutines.*
import kotlin.coroutines.coroutineContext

// 如果使用GlobalScope.launch创建协程时，会创建一个顶层协程。
// 由于它没有CoroutineScope，因而此协程没有父协程。
// 虽然它很轻量，但它运行时仍会消耗一些内存资源。即使没有保持对
// 新启动的协程的引用，它还会继续运行。
// 如果协程中的代码挂起了会怎么样（例如，我们错误地延迟了太长时间），
// 如果我们启动了太多的协程并导致内存不足会怎么样？ 必须手动保持对
// 所有已启动协程的引用并 join 之很容易出错。
//
// 比如你在在一个Activity中使用它创建一个协程执行耗时的逻辑，然而
// 在Activity已经finish还没有进行回调，那么就会产生一些额外的资源消耗。
//
// 解决办法就是使用结构化并发，可以在执行操作所在的指定作用域内启
// 动协程， 而不是使用GlobalScope启动。

// 协程是可以 在指定作用域内启动协程的。协程构建器都将 CoroutineScope 的
// 实例添加到其代码块所在的作用域中，外部协程（示例中的 runBlocking）直到
// 在其作用域中启动的所有协程都执行完毕后才会结束

// 使用结构化的并发了，将 deferred1、deferred2 置于同一个作用域上，
// 作用域内的协程称为外部协程的子协程，那么当其中外部协程被取消或者
// 子协程异常时，作用域中的所有子协程都会被取消。

fun main() = runBlocking {

   launch {
        val score = getScore()
        println("$score")
    }

    // 当使用GlobalScope.launch创建了协程。在协程内部，有
    // 一个死循环，每间隔100ms，打印一次“aaaa”。而在后面，
    // 又使用了join等待此协程的挂起代码块执行结束。这样，
    // 会导致程序一直卡在这里。
    var jobGlobal: Job? = null
    val jobParent = launch {
        jobGlobal = GlobalScope.launch(NonCancellable) {
            while (true) {
                delay(1000)
                println("aaaa")
            }
        }

        launch {
            while (true) {
                delay(1000)
                println("bbbb")
            }
        }
    }

    delay(3000)
    jobGlobal?.join()
    jobParent.cancel()

    println("runBlocking --> end")
}

data class Score(
    val englishScore: Int,
    val chineseScore: Int
)

suspend fun getScore() : Score{

    return withContext(coroutineContext) {
        val englishDeffered = async { getEnglishScore() }
        val chineseDeffered = async { getChineseScore() }
        Score(englishDeffered.await(), chineseDeffered.await())
    }
}

suspend fun getEnglishScore(): Int {
    return withContext(coroutineContext) {
        delay(2000)
        100
//        throw Exception("aaaa")
    }
}

suspend fun getChineseScore(): Int {
    return withContext(coroutineContext) {
        delay(3000)
        99
    }
}